package com.hm.hall.commons.util;


import com.hm.hall.commons.constans.ErrorCode;
import com.hm.hall.commons.framework.PropertyPlaceholderConfigurerAppendCfgByDB;
import com.hm.hall.commons.constans.ConsoleConfigKeysConstants;
import org.apache.log4j.Logger;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;


/**
 * @Description: 关于action的一些工具
 * @author:雷建军
 * @Company:
 * @create:2014年7月25日 上午10:13:05
 * @update:2014年7月25日 上午10:13:05
 */
public class ActionUtils {

    static Logger log = Logger.getLogger(ActionUtils.class);
    private static String serverVersion = null;
    private static Logger LogUtils = Logger.getLogger(ActionUtils.class);
    /**
     * 是否是开发环境
     */
    private static Boolean isDevEnv = null;
    /**
     * 是否是体验测试环境
     */
    private static Boolean isTestEnv = null;
    /**
     * 是否是正式环境
     */
    private static Boolean isIdcEnv = null;
    /**
     * *********************
     * 获得 配置文件属性
     */
    private static ResourceBundle appCfg = null;
    private static String envPort = null;
    private static String envIp = null;

    /**
     * @param millis 毫秒数 throws
     * @author 雷建军
     * @time 2014年8月18日 下午3:48:40
     * @Description: 延时方法, 用来调试,模拟网络延时,
     */
    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);// 括号里面的5000代表5000毫秒，也就是5秒，可以该成你需要的时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * @author 雷建军
     * @Description: 获得当前URL
     */
    public static String getCurrentUrl() {
        HttpServletRequest request = getRequest();
        return request.getRequestURL().toString();
    }

    public static String getStaticPath() {
        String path = ActionUtils.class.getResource("/").toString();
        path = path.replace("file:", ""); //去掉file:
        path = path.replace("classes\\", ""); //去掉class\
        path = path.replace("classes/", ""); //去掉class\
        if (path.contains(":")) {
            path = path.replace('/', '\\'); // 将/换成\
            path = path.substring(1); //去掉第一个\,如 \D:\JavaWeb...
        }

        log.info("-------path--------" + path);
        return path + "/statics";
    }

    /**
     * @author 雷建军
     * @Description: 根据请求 获得域名  // 开头自动选择域名的,不带http 前缀
     */
    public static String getDomain() {
        HttpServletRequest request = getRequest();
        String domain;
        if (isDevEnv()) {
            domain = "//" + request.getServerName() + ":" + request.getServerPort();
        } else {
            domain = "//" + request.getServerName();
        }
        // 正式改测试环境 时兼容下
        if (isDevEnv() && (domain.contains("backend") || domain.contains("localhost") || domain.contains("game_hoobic_com"))) {
            domain = "//tgame.hoobic.com";
        }
        return domain;
    }

    /**
     * 获得服务器版本号,  测试环境下时间戳,,正式化根据发布日期变更
     */
    public static String getServerVersion() {
        if (isDevEnv()) {
            serverVersion = "V" + System.currentTimeMillis();
        } else if (serverVersion == null) {
            serverVersion = "V" + DateUtils.formatDate(new Date(), "yyyy_MM_dd_HH_mm");
        }
        return serverVersion;
    }

    /**
     * @author 雷建军
     * @Description: 获得ContextPath
     */
    public static String getPath() {

        return "wepoker";
    }

    /**
     * 获得项目域名
     *
     * @return
     */
    public static String getProductDomain() {
        if (isDevEnv()) {
            String serverName = getRequest().getServerName();
            // 正式改测试环境 时兼容下
            if ((serverName.contains("backend") || serverName.contains("localhost") || serverName.contains("game_hoobic_com"))) {
                return "https:" + getDomain();
            }
            return "http:" + getDomain() + getPath();
        } else {
            return ConsoleConfigUtils.getStringConfig(ConsoleConfigKeysConstants.GAME_PRODUCT_PUBLIC_IP);
        }
    }

    public static String strToURL(String str) {
        String result = null;
        try {
            result = URLEncoder.encode(str, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String urlToStr(String url) {
        String result = null;
        try {
            result = URLDecoder.decode(url, "utf-8");
            // 空格替换成加号
            result = result.replaceAll(" ", "+");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * @param jsonString void throws
     * @author 雷建军
     * @time 2014年6月4日 下午3:16:53
     * @Description: 在action中调用response.getWriter().write(text);。可作为 ajax返回值
     */
    public static void printWriter(String jsonString) {
        HttpServletResponse response = getResponse();
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("Cache-Control", "no-cache"); // HTTP 1.1
        response.setHeader("Pragma", "no-cache"); // HTTP 1.0
        response.setDateHeader("Expires", 0); // prevents caching at the proxy
        // server
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.write(jsonString);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != out) {
                out.flush();
                out.close();
            }
        }
    }


    /*********************************************** 文件上传下载 *******************************************************************/

    /**
     * ajax返回的返回值。value:返回的内容
     */
    public static <T> void ajaxReturn(T value) {
        String resValue = value.toString();
        printWriter(resValue);
    }

    public static void ajaxRestObject(ErrorCode errorCode) {
        ajaxRestObject(errorCode.code, errorCode.msg);
    }

    /*********************************************** 几大作用域作用域 方法 *******************************************************************/

    public static void ajaxRestObject(int errorCode, String errMsg) {
        ajaxReturn(new StringBuilder("{ \"errorCode\" : ").append(errorCode).append(",\"errMsg\":\"").append(errMsg).append("\"}"));
    }

    public static void ajaxRestObject(int errorCode, String errMsg, String dataJSON) {
        if (dataJSON == null) {
            dataJSON = "";
        }
        ajaxReturn(new StringBuilder("{ \"errorCode\" : ").append(errorCode).append(",\"errMsg\":\"").append(errMsg).append("\",\"data\":\"").append(dataJSON).append("\"}"));
    }

    /**
     * ajax返回状态, 返回 new StringBuffer("{ \"state\" : \"").append( state ).append("\"}")
     */
    public static <T> void ajaxState(T state) {
        ajaxReturn(new StringBuilder("{ \"state\" : \"").append(state).append("\"}"));
    }

    /**
     * set 排序
     */
    public static Set sortBySet(Set source, Comparator comparator) {
        Set<Object> treeSet = new TreeSet<Object>(comparator);
        treeSet.addAll(source);
        return treeSet;
    }

    /**
     * 统计字符串中  字符出现的次数
     */
    public static int stringCharCount(String str, char c) {
        int count = 0;
        for (int i = 0, l = str.length(); i < l; i++) {
            if (c == str.charAt(i)) {
                count++;
            }
        }
        return count;
    }

    /**
     * @param request
     * @return List<MultipartFile> throws
     * @author 雷建军
     * @time 2014年8月13日 上午11:06:12
     * @Description: 文件上传方法
     * 使用spring-mvc的上传类从request中获得List<MultipartFile>上传的文件集.
     * (ps:速度比流方式快很多倍 , 一个4M的文件 流的方式的运行时间：14712ms multipartFile方法的运行时间：4ms)
     * 1.  拷贝文件:
     * for (MultipartFile multipartFile : ActionUtils.getUploadFiles(request)) {
     * multipartFile.transferTo(new File("D:/" + multipartFile.getOriginalFilename()));
     * }
     * 2. getBytes得到 数据.等等...方法..
     * <p/>
     * 进度条:
     * 1. 使用html5做进度条,
     * 2. 重写CommonsMultipartResolver 获得进度信息,前端轮询取得信息...
     */
    public static List<MultipartFile> getUploadFiles(HttpServletRequest request) {
        // 将当前上下文初始化给 CommonsMutipartResolver （多部分解析器）
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        // 检查form中是否有enctype="multipart/form-data"
        if (multipartResolver.isMultipart(request)) {
            // 将request变成多部分request
            MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
            // 获取multiRequest 中所有的文件名
            Iterator<String> iter = multiRequest.getFileNames();

            List<MultipartFile> multipartFiles = new ArrayList<MultipartFile>();
            while (iter.hasNext()) {
                // 一次遍历所有文件
                MultipartFile file = multiRequest.getFile(iter.next().toString());
                multipartFiles.add(file);
            }
            return multipartFiles;
        }
        return null;
    }

    /**
     * @param file
     * @time 2014年8月22日 下午5:34:05
     * @Description: 文件下载方法
     */
    public static void downloadFile(File file) {
        String fileName = file.getName();
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } catch (UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        ActionUtils.getResponse().setContentType("application/zip");
        ActionUtils.getResponse().addHeader("Content-Disposition", "attachment;filename=" + fileName);
        OutputStream outp = null;
        FileInputStream in = null;
        try {
            outp = ActionUtils.getResponse().getOutputStream();
            in = new FileInputStream(file);
            byte[] b = new byte[1024];
            int i = 0;
            while ((i = in.read(b)) > 0) {
                outp.write(b, 0, i);
            }
            outp.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outp != null) {
                try {
                    outp.close();
                    outp = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * @param arg
     * @return String throws
     * @author 雷建军
     * @time 2014年6月13日 下午3:29:19
     * @Description: 从request中取指定值。等价=request.getParameter(arg);
     */
    public static String getParameter(String arg) {
        return getRequest().getParameter(arg);
    }

    /**
     * @author 雷建军
     * @time 2014年6月13日 下午3:29:19
     * @Description: 等价于=request.getAttribute(arg); throws
     */
    public static Object getAttribute(String arg) {
        return getRequest().getAttribute(arg);
    }

    /**
     * @author 雷建军
     * @time 2014年6月13日 下午3:29:19
     * @Description: 等价于=request.setAttribute(key,value); throws
     */
    public static void setAttribute(String key, Object value) {
        getRequest().setAttribute(key, value);
    }

    /**
     * 获得几大作用域
     */
    public static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    // 这个从request里取的(spring mvc只有response获取不到,所以自己手动保存)
    public static HttpServletResponse getResponse() {
        return (HttpServletResponse) getRequest().getAttribute("[save][response]");
    }

    public static void setResponse(HttpServletResponse response) {
        getRequest().setAttribute("[save][response]", response);
    }

    /**
     * 获得log4j
     */
    public static Logger getLogger() {
        return LogUtils;
    }

    /**
     * 获得utf-8 字符串 来自GBK字符串
     */
    public static String getUTF8StringByGBK(String str) {
        try {
            str = new String(str.getBytes("GBK"), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    public static void sendRedirect(String url) {
        try {
            ActionUtils.getResponse().sendRedirect(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static boolean isAjaxRequest() {
        String header = getRequest().getHeader("X-Requested-With");
        return header != null && "XMLHttpRequest".equals(header);
    }

    /**
     * 判断微信客户端访问
     */
    public static boolean isWeixinRequest() {
        String userAgent = getRequest().getHeader("user-agent");
        return userAgent != null && userAgent.toLowerCase().contains("micromessenger");
    }

    /**
     * 判断QQ客户端访问
     */
    public static boolean isQQRequest() {
        String userAgent = getRequest().getHeader("user-agent");
        return userAgent != null && userAgent.toLowerCase().contains("qq/");
    }

    /**
     * 是否是开发环境
     */
    public static boolean isDevEnv() {
        if (ActionUtils.isDevEnv == null) {
            ActionUtils.isDevEnv = "dev".equals(System.getProperty("spring.profiles.active"));
        }
        return ActionUtils.isDevEnv;
    }


    /**
     * 解析查询参数
     */

    public static String getEnv() {
        return System.getProperty("env");
    }

    /**
     * 是否是测试环境
     */
    public static boolean isTestEnv() {
        if (ActionUtils.isTestEnv == null) {
            ActionUtils.isTestEnv = "test".equals(System.getProperty("spring.profiles.active"));
        }
        return ActionUtils.isTestEnv;
    }

    /**
     * 是否是正式环境
     */
    public static boolean isIdcEnv() {
        if (ActionUtils.isIdcEnv == null) {
            ActionUtils.isIdcEnv = "idc".equals(System.getProperty("spring.profiles.active"));
        }
        return ActionUtils.isIdcEnv;
    }

    /**
     * 取得带相同前缀的Request Parameters, 返回的结果的Parameter名已去除前缀.
     */
    public static Map<String, Object> parseParameters(ServletRequest request, String prefix) {
        if (request == null) {
            return new HashMap<>();
        }
        Enumeration paramNames = request.getParameterNames();
        Map<String, Object> params = new TreeMap<String, Object>();
        if (prefix == null) {
            prefix = "";
        }
        while ((paramNames != null) && paramNames.hasMoreElements()) {
            String paramName = (String) paramNames.nextElement();
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                String[] values = request.getParameterValues(paramName);
                try {
                    if ((values == null) || (values.length == 0)) {
                        // Do nothing, no values found at all.
                        continue;
                    }

                    String val = values.length > 1 ? values.toString().trim() : values[0].trim();
                    val = URLDecoder.decode(val, "UTF-8");
                    // 如果是时间格式转为 Date
                    if (val.length() == 10 && val.charAt(4) == '-' && val.charAt(7) == '-') {
                        params.put(unprefixed, DateUtils.parseDate(val));
                    } else {
                        params.put(unprefixed, val);
                    }

                } catch (UnsupportedEncodingException e) {

                }
            }
        }
        return params;
    }

    // app config
    public static ResourceBundle getAppCfg() {
        return appCfg == null ? ResourceBundle.getBundle("configs-" + System.getProperty("spring.profiles.active")) : appCfg;
    }

    /**
     * 注意获得系统配置时,配置文件和来自DB 的配置
     *
     * @param key
     * @return
     */
    public static String getRsAppCfg(String key) {
        // 本机 代理测试的
//        if (ActionUtils.isDevEnv() && IPUtil.getLocalIpAddr().contains("192.168.1.173")) {
//            if ( key.equals(ConsoleConfigKeysConstants.GAME_WX_DOMAIN)) {
//                return "http://lehman.w3.luyouxia.net/game";
//            } else if ( key.equals(ConsoleConfigKeysConstants.GAME_APPID)) {
//                return "wx32a858dc34925bd3";
//            } else if ( key.equals(ConsoleConfigKeysConstants.GAME_APPSECRET)) {
//                return "e665131330ca95fe86bd68c7cbd8a786";
//            }
//        }

        String cfgStr = null;
        try {
            cfgStr = getAppCfg().getString(key);
        } catch (Exception ignored) {
        }
        if (cfgStr == null) {
            cfgStr = PropertyPlaceholderConfigurerAppendCfgByDB.getDbSysCfgProper(key);
        }
        return cfgStr;
    }

    /**
     * 转换版本号
     *
     * @param appVersion
     * @return
     */
    public static int convertVersion(String appVersion) {
        int appVersionNumber = 0;
        int number0digit = 1000000;
        int number1digit = 10000;
        int number2digit = 1;
        String[] numberList = appVersion.split("\\.");
        appVersionNumber += Integer.valueOf(numberList[0]) * number0digit;
        if (Integer.valueOf(numberList[1]) * number1digit > 100000) {
            appVersionNumber += Integer.valueOf(numberList[1]) * number1digit / 10;
        } else {
            appVersionNumber += Integer.valueOf(numberList[1]) * number1digit;
        }
        appVersionNumber += Integer.valueOf(numberList[2]) * number2digit;
        return appVersionNumber;
    }

    public static String getEnvPort() {
        if (ActionUtils.envPort == null) {
            ActionUtils.envPort = System.getProperty("envport");
        }
        return ActionUtils.envPort;
    }

    public static String getEnvIp() {
        if (ActionUtils.envIp == null) {
            ActionUtils.envIp = System.getProperty("envip");
        }
        return ActionUtils.envIp;
    }


}
